# -*- coding: utf-8 -*-

from w.blocks.containers.block import Block

from w.html.doctypes.preferable import Table as TableTag
from w.html.doctypes.preferable import Thead,Tbody,Tr,Td,Th

from w.utils.dobject.strict import DynamicInit

from w.javascript.base import JSTranslator

class Table(Block):
    generateHeadTrIDs = True
    generateBodyTrIDs = True
    generateTdIDs = True
    generateThIDs = True

    def __init__(self, head=None, body=None, dimensions=None, *argv, **kwargv):
        Block.__init__(self)
	
        body = body if body else []
        head = head if head else []

        self.rules = DynamicInit(HeadTr={}, BodyTr={}, Td={}, Th={})

        self.replaceBody(body)
        self.replaceHead(head)

        self.dimensions = dimensions
        if not body and not head and self.dimensions:
            self.head = Thead(Tr() for i in range(dimensions[0][0]))
            self.body = Tbody(Tr() for i in range(dimensions[1][0]))

        self.tag = TableTag(*argv, **kwargv)
        self.html = self.tag.html

    def generateBodyTrID(self, seed):
        return '%sbodyRow%s'%(self.blockID, seed)

    def generateHeadTrID(self, seed):
        return '%sheadRow%s'%(self.blockID, seed)

    def generateTdID(self, seed1, seed2):
        return '%sbodyElem%s%s'%(self.blockID, seed1, seed2)

    def generateThID(self, seed1, seed2):
        return '%sheadElem%s%s'%(self.blockID, seed1, seed2)

    def ruledHeadTr(self, tr):
        d = {'ID': tr.html.id}
	
        for name,value in self.rules.HeadTr.items():
            if callable(value) and not isinstance(value, JSTranslator):
                setattr(tr.html, name, value(**d))
            else:
                setattr(tr.html, name, value%d)
        return tr

    def ruledBodyTr(self, tr):
        d = {'ID': tr.html.id}
        for name,value in self.rules.BodyTr.items():
            if callable(value) and not isinstance(value, JSTranslator):
                setattr(tr.html, name, value(**d))
            else:
                setattr(tr.html, name, value%d)
        return tr

    def ruledTd(self, td):
        d = {'ID': td.html.id}
        for name,value in self.rules.Td.items():
            if callable(value) and not isinstance(value, JSTranslator):
                setattr(td.html, name, value(**d))
            else:
                setattr(td.html, name, value%d)
        return td

    def ruledTh(self, th):
        d = {'ID': th.html.id}
        for name,value in self.rules.Th.items():
            if callable(value) and not isinstance(value, JSTranslator):
                setattr(th.html, name, value(**d))
            else:
                setattr(th.html, name, value%d)
        return th

    def createTr(self, rowNum, content=None, head=False):
        if head:
            tr = Tr(content,hid=self.generateHeadTrID(rowNum)) if self.generateHeadTrIDs else Tr()
            tr = self.ruledHeadTr(tr)
        else:
            tr = Tr(content,hid=self.generateBodyTrID(rowNum)) if self.generateBodyTrIDs else Tr()
            tr = self.ruledBodyTr(tr)
        return tr

    def createTd(self, rowNum, colNum, content=None):
        if self.generateTdIDs:
            td = Td(content,hid=self.generateTdID(rowNum,colNum))
        else:
            td = Td(content)
        return self.ruledTd(td)

    def createTh(self, rowNum, colNum, content=None):
        if self.generateThIDs:
            th = Th(content,hid=self.generateThID(rowNum,colNum))
        else:
            th = Th(content)
        return self.ruledTh(th)

    def replaceBody(self,src):
        self.body = Tbody()
        for i in range(len(src)):
            tr = self.createTr(i)
            for j in range(len(src[i])):
                td = self.createTd(i,j,src[i][j])
                tr.append(td)
            self.body.append(tr)

    def replaceHead(self,src):
        self.head = Thead()
        for i in range(len(src)):
            tr = self.createTr(i,head=True)
            for j in range(len(src[i])):
                th = self.createTh(i,j,src[i][j])
                tr.append(th)
            self.head.append(tr)

    def replaceBodyWithObjects(self,src,names):
        self.body = Tbody()
        for i in range(len(src)):
            tr = self.createTr(i)
            for j in range(len(names)):
                td = self.createTd(i,j,getattr(src[i],names[j]))
                tr.append(td)
            self.body.append(tr)

    #only one-dimensional headers are supported
    def replaceTableWithObjects(self,src,names):
        self.replaceHead([names])
        self.replaceBodyWithObjects(src,names)

    def insertBodyRow(self,rowSrc,rowNum=0):
        if self.body[0] and len(rowSrc) != len(self.body[0]):
            raise Error('Row size of %s is unaccepted. Need %s.'%(len(rowSrc),fLen))
        self.body.insert(rowNum, self.createTr(rowNum,[Td(elem) for elem in rowSrc]))

    def insertHeadRow(self,rowSrc,rowNum=0):
        if self.head[0] and len(rowSrc) != len(self.head[0]):
            raise Error('Row size of %s is unaccepted. Need %s.'%(len(rowSrc),fLen))
        self.head.insert(rowNum, self.createTr(rowNum,[Th(elem) for elem in rowSrc],head=True))

    #need dimensions constructor param if body and/or head are unset
    def insertCol(self,colSrc,colNum=0):
        fLen = len(self.body)+len(self.head)
        if len(colSrc) != fLen:
            raise Error('Col size of %s is unaccepted. Need %s.'%(len(colSrc),fLen))
        hSize = len(self.head)
        for i in range(hSize):
            self.head[i].insert(colNum, Th(colSrc[i]))
        for i in range(hSize,len(colSrc)):
            self.body[i-hSize].insert(colNum, Td(colSrc[i]))

    #need dimensions constructor param if body and/or head are unset
    def appendCol(self,colSrc):
        fLen = len(self.body)+len(self.head)
        if len(colSrc) != fLen:
            raise Error('Col size of %s is unaccepted. Need %s.'%(len(colSrc),fLen))
        hSize = len(self.head)
        for i in range(hSize):
            self.head[i].append(Th(colSrc[i]))
        for i in range(hSize,len(colSrc)):
            self.body[i-hSize].append(Td(colSrc[i]))

    def make(self):
        self.tag.extend([self.head,self.body])
        return Block.make(self, [self.tag,])

